home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume89
/
languags
/
zc.2
< prev
next >
Wrap
Text File
|
1989-03-08
|
64KB
|
3,694 lines
Path: xanth!nic.MR.NET!csd4.milw.wisc.edu!mailrus!bbn!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v89i029: zc - c compiler, Part02/04
Message-ID: <12043@swan.ulowell.edu>
Date: 8 Mar 89 03:03:15 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 3683
Approved: page@swan.ulowell.edu
Submitted-by: monty@brahms.Berkeley.EDU (Joe Montgomery)
Posting-number: Volume 89, Issue 29
Archive-name: languages/zc.2
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# d2.c
# decl.c
# expr.c
# fix.c
# fun.c
# g2.c
# This archive created: Tue Mar 7 21:49:30 1989
cat << \SHAR_EOF > d2.c
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* d2.c
*
* Declaration subroutines
*
* Mostly routines for initializations
*/
#include <stdio.h>
#include "param.h"
#include "tok.h"
#include "nodes.h"
#include "cookie.h"
#if MMCC
overlay "pass2"
#endif
extern NODEP cur;
extern NODEP symtab[];
extern level;
extern int oflags[];
#define debugi oflags['i'-'a']
su_size(lp, cp, xp, isunion)
register long *lp;
char *cp;
register NODE *xp;
{
long sz;
char al;
sz = xp->n_tptr->t_size;
al = xp->n_tptr->t_aln;
if (isunion) {
*lp = *lp > sz ? *lp : sz;
} else {
while (al & (*lp)) { /* align new field */
(*lp)++;
xp->e_offs++;
}
*lp += sz;
}
*cp = *cp > al ? *cp : al;
}
lc_size(lp, rp, xp)
register long *lp;
int *rp;
register NODE *xp;
{
long sz;
char al;
long arg_size();
if (level > 1 && xp->e_sc == K_REGISTER) {
if (lc_reg(rp, xp))
return;
else
xp->e_sc = K_AUTO;
}
if (xp->e_sc == K_AUTO || level == 1) {
sz = xp->n_tptr->t_size;
al = xp->n_tptr->t_aln;
while (al & (*lp)) { /* align new field */
(*lp)++;
xp->e_offs++;
}
if (level == 1) {
sz = arg_size(sz,xp);
xp->e_offs += ARG_BASE + *lp;
}
*lp += sz;
if (level != 1)
xp->e_offs = LOC_BASE - *lp;
}
}
su_fld(lp, alp, xp, fldw, fop)
register long *lp;
char *alp;
register NODE *xp;
int *fop;
{
if (*alp < ALN_I)
*alp = ALN_I;
if (fldw == 0) {
afterfld(lp, fop);
return;
}
if (fldw + *fop > 8*SIZE_I)
afterfld(lp, fop);
if (xp) {
xp->e_fldw = fldw;
xp->e_fldo = *fop;
}
*fop += fldw;
}
afterfld(szp, fop)
long *szp;
int *fop;
{
if (*fop) {
*szp += SIZE_I;
*fop = 0;
}
}
ok_gsh(sc, np)
NODE *np;
{
if (sc == K_REGISTER || sc == K_AUTO) {
error("reg/auto outside fun");
return 0;
}
return ok_ty(np, NULL);
}
ok_gx(np, endp)
NODEP np, endp;
{
if (np)
return ok_ty(np->n_tptr, endp);
return 0;
}
ok_lsh(sc, np)
NODE *np;
{
return ok_ty(np, NULL);
}
arytoptr(np)
NODEP np;
{
NODEP tp = np->n_tptr;
NODEP copyone();
if (np->n_flags & N_COPYT) { /* cant change if a dupl. */
tp = copyone(tp);
np->n_tptr = tp;
np->n_flags &= ~N_COPYT;
}
tp->t_token = STAR;
strcpy(tp->n_name, "Aptr to");
}
ok_lx(np,endp)
NODEP np, endp;
{
if (np) {
if (level == 1 && np->n_tptr->t_token == '[')
arytoptr(np);
return ok_ty(np->n_tptr, endp);
}
return 0;
}
ok_suh(np)
NODEP np;
{
return 1;
}
ok_sux(np, endp)
NODEP np, endp;
{
if (np)
return ok_ty(np->n_tptr, endp);
return 0;
}
ok_enx(np, endp)
NODEP np, endp;
{
if (np && np->n_tptr == endp) /* no modifiers */
return 1;
return 0;
}
ok_cast(np, endp)
NODEP np, endp;
{
if (np)
return ok_ty(np, endp);
return 0;
}
ok_ty(np, endp)
register NODEP np, endp;
{
NODEP child;
long csize;
long conlval();
if (np == endp)
return 1;
child = np->n_tptr;
if (child) {
if (ok_ty(child, endp) == 0)
return 0;
csize = child->t_size;
}
switch (np->t_token) {
case STAR:
np->t_size = SIZE_P;
np->t_aln = ALN_P;
break;
case '(':
/* size 0 okay - fun ret void */
if (child->t_token == '[') {
error("bad func");
return 0;
}
/* size 0 */
break;
case '[':
if (csize == 0) {
error("bad array");
return 0;
}
if (np->n_right) {
csize *= conlval(np->n_right);
np->n_right = NULL;
np->t_size = csize;
}
np->t_aln = child->t_aln;
break;
default:
return 1;
}
return 1;
}
ok_revx(rv,forcast)
NODEP rv;
{
if (rv == NULL)
return 1;
if (forcast == 0 && rv->e_token != ID) {
error("need ID");
return 0;
}
if (forcast && rv->e_token == ID) {
error("ID in cast");
return 0;
}
return 1;
}
opt_ginit(xp)
NODEP xp;
{
if (xp->e_token != ID)
return;
if (xp->n_tptr->t_token == '(')
return;
switch (xp->e_sc) {
case K_STATIC:
case HERE_SC:
if (cur->e_token == '=') {
out_gv(xp, 0); /* place in data segment */
fadvnode();
g_init(xp->n_tptr);
} else
out_gv(xp, 1); /* place in BSS segment */
break;
/* ? added external case ? */
case K_EXTERN:
out_gv(xp,0);
}
}
opt_linit(xp)
NODEP xp;
{
if (xp->e_token != ID)
return;
if (xp->n_tptr->t_token == '(')
return;
switch (xp->e_sc) {
case K_STATIC:
if (cur->e_token == '=') {
out_gv(xp, 0);
fadvnode();
g_init(xp->n_tptr);
} else
out_gv(xp, 1);
to_text();
break;
case K_AUTO:
case K_REGISTER:
if (cur->e_token == '=')
a_init(xp);
break;
}
}
a_init(op)
NODEP op;
{
register NODEP np, xp;
NODEP assignx(), copynode();
np = cur; advnode();
xp = assignx();
op = copynode(op);
np->n_left = op;
np->n_right = xp;
np->e_type = E_BIN;
do_expr(np, FORSIDE);
return;
}
opt_enval(intp)
int *intp;
{
NODEP np;
NODEP questx();
if (cur->e_token == '=') {
fadvnode();
np = questx();
*intp = conxval(np);
return;
}
}
opt_field(xp,wdp,isunion)
NODE *xp;
int *wdp;
{
NODEP np;
NODEP questx();
int i;
*wdp = -1;
if (isunion) return;
if (cur->e_token == ':') {
fadvnode();
np = questx();
i = conxval(np);
if (i > 8*SIZE_I) {
error("field too big");
i = 8*SIZE_I;
}
if (xp) {
if (i <= 0 || bad_fty(xp->n_tptr)) {
error("bad field");
return;
}
} else if (i < 0) {
error("neg field width");
return;
}
*wdp = i;
return;
}
}
bad_fty(tp)
NODEP tp;
{
int tok;
tok = tp->t_token;
if (tok == K_INT || tok == K_UNSIGNED)
return 0;
return 1;
}
field(xp, wd, ofp)
NODEP xp;
int *ofp;
{
}
NODEP
def_type()
{
NODEP bas_type();
return bas_type(K_INT);
}
#define NSC LAST_SC-FIRST_SC+1
#define NBAS LAST_BAS-FIRST_BAS+1
NODE basics[NBAS];
NODE str_ptr, fun_int;
struct bt {
char *name;
int size;
char align;
} btbl[] = {
{"Uchar", SIZE_C, ALN_C},
{"Ulong", SIZE_L, ALN_L},
{"Long", SIZE_L, ALN_L},
{"Short", SIZE_S, ALN_S},
{"Uns", SIZE_U, ALN_U},
{"Int", SIZE_I, ALN_I},
{"Char", SIZE_C, ALN_C},
{"Float", SIZE_F, ALN_F},
{"Dbl", SIZE_D, ALN_D},
{"Void", 0},
};
NODEP
bas_type(btype)
{
NODEP rv;
static once = 0;
if (once == 0) {
once++;
sprintf(str_ptr.n_name, "Ptr to");
str_ptr.t_token = STAR;
str_ptr.n_tptr = bas_type(K_CHAR);
str_ptr.n_flags = N_COPYT;
str_ptr.t_size = SIZE_P;
str_ptr.t_aln = ALN_P;
sprintf(fun_int.n_name, "Fun ret");
fun_int.t_token = '(';
fun_int.n_tptr = bas_type(K_INT);
fun_int.n_flags = N_COPYT;
}
if (btype == SCON)
return &str_ptr;
else if (btype == '(')
return &fun_int;
rv = &basics[btype-FIRST_BAS];
if (rv->t_token == 0) {
rv->t_token = btype;
rv->t_size = btbl[btype-FIRST_BAS].size;
rv->t_aln = btbl[btype-FIRST_BAS].align;
sprintf(rv->n_name, btbl[btype-FIRST_BAS].name);
}
return rv;
}
/* new function name seen in expr */
NODEP
new_fun(op)
NODE *op;
{
NODEP np;
NODEP copyone();
/* we know left, right and tptr are NULL */
np = copyone(op); /* ID node */
np->n_tptr = bas_type('(');
np->n_flags = N_COPYT;
np->e_sc = K_EXTERN;
new_sym(symtab, np);
return np;
}
/* declare arg name as int */
def_arg(listpp, op)
NODE **listpp, *op;
{
register NODEP np;
NODEP copyone();
np = copyone(op);
np->n_tptr = bas_type(K_INT);
np->n_flags = N_COPYT;
np->e_sc = K_AUTO;
new_sym(listpp, np);
}
/* initialize 0 or 1 thing of any type (tp) */
g_init(tp)
register NODEP tp;
{
int nsee;
long sz;
int oldsize;
int seebr = 0;
if (cur->e_token == SCON &&
tp->t_token == '[' &&
tp->n_tptr->t_token == K_CHAR) { /* hack for SCON ary */
nsee = out_scon(cur);
fadvnode();
a_fix(tp, nsee);
return 1;
}
if (cur->e_token == '{') {
fadvnode();
seebr = 1;
}
switch (tp->t_token) {
case '[':
if (tp->t_size)
oldsize = tp->t_size / tp->n_tptr->t_size;
else
oldsize = 0;
nsee = inita(tp->n_tptr, oldsize);
if (nsee)
a_fix(tp, nsee);
break;
case K_STRUCT:
o_aln(tp->t_aln);
nsee = inits(tp->n_right);
break;
case K_UNION:
o_aln(tp->t_aln);
nsee = g_init(tp->n_right->n_tptr);
if (nsee) {
sz = tp->t_size - tp->n_right->n_tptr->t_size;
if (sz)
o_nz(sz, 0);
}
break;
default:
nsee = init1(tp);
break;
}
if (seebr) {
if (cur->e_token == ',')
fadvnode();
eat('}');
}
return nsee ? 1 : 0;
}
/* initialize one (or 0) scalar to an expr */
init1(tp)
register NODEP tp;
{
NODEP xp;
NODEP assignx();
if (debugi) {
printf("init1");
printnode(tp);
}
xp = assignx();
if (xp) {
if (debugi)
printnode(xp);
o_vinit(tp, xp);
return 1;
} else
return 0;
}
/* set array size or fill array with zeros */
a_fix(tp, nsee)
register NODEP tp;
{
int oldsize;
if (tp->t_size) {
oldsize = tp->t_size / tp->n_tptr->t_size;
if (oldsize > nsee) {
o_nz(tp->n_tptr->t_size * (oldsize-nsee),
tp->n_tptr->t_aln);
} else if (oldsize < nsee) {
error("too many init exprs");
}
} else
tp->t_size = nsee * tp->n_tptr->t_size;
}
/* initialize up to max items of type tp */
/* if max is 0, any number is okay */
inita(tp, maxi)
NODEP tp;
{
int nsee;
nsee = g_init(tp);
if (nsee == 0)
return 0;
while (cur->e_token == ',') {
if (nsee == maxi)
break;
fadvnode();
nsee += g_init(tp);
}
return nsee;
}
/* initialize (possible) structure */
inits(np)
register NODEP np;
{
int see1;
see1 = g_init(np->n_tptr);
if (see1 == 0)
return 0;
while (np->n_next) {
np = np->n_next;
if (cur->e_token == ',') {
fadvnode();
see1 = g_init(np->n_tptr);
} else
see1 = 0;
if (see1 == 0)
z_init(np->n_tptr);
}
return 1;
}
z_init(tp)
register NODEP tp;
{
switch (tp->t_token) {
case '[':
case K_STRUCT:
case K_UNION:
o_nz(tp->t_size, tp->t_aln);
break;
default:
out_zi(tp);
}
}
SHAR_EOF
cat << \SHAR_EOF > decl.c
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* decl.c
*
* Do all declarations
*
* Currently,
* struct tags are local
* struct members are tied to the struct
* enum tags are ignored
* enum members are local
*/
#include <stdio.h>
#include "param.h"
#include "tok.h"
#include "nodes.h"
extern NODE *cur;
extern level;
NODEP symtab[NHASH], tagtab;
extern NODE *blktab;
NODEP alltags(), allsyms(), llook(), hlook();
extern int oflags[];
#define debug oflags['v'-'a']
/* look for global data decls
return when see something weird
return last ID declared */
NODEP
glb_decls()
{
register NODEP head, xp;
NODEP d_type(), def_type(), d_declr();
int sclass;
for(;;) {
sclass = d_scl(HERE_SC);
head = d_type();
if (head == NULL)
head = def_type();
if (ok_gsh(sclass, head) == 0)
continue;
more:
xp = d_declr(head,0);
if (ok_gx(xp,head)) {
xp->e_sc = sclass;
opt_ginit(xp);
new_sym(symtab,xp);
if (xp->n_tptr->t_token == '(') { /* func */
if (cur->e_token == ',' ||
cur->e_token == ';')
fix_fun(xp);
else
return xp;
}
}
if (cur->e_token == ',') {
fadvnode();
goto more;
}
if (cur->e_token == ';') {
fadvnode();
} else
return NULL;
}
}
/* do local or arg decls
return 1 if see something */
loc_decls()
{
register NODEP head, xp;
NODEP d_type(), def_type(), d_declr();
int sclass;
int regs;
long size;
int rv = 0;
size = level > 2 ? blktab->n_next->b_size : 0;
regs = level > 1 ? blktab->n_next->b_regs : 0;
while (is_ty_start()) {
rv++;
sclass = d_scl(K_AUTO);
head = d_type();
if (head == NULL)
head = def_type();
if (ok_lsh(sclass, head) == 0)
continue;
more:
xp = d_declr(head,0);
if (ok_lx(xp,head)) {
xp->e_sc = sclass;
if (level > 1) /* not args */
lc_size(&size, ®s, xp);
new_sym(&blktab->b_syms,xp);
fix_fun(xp);
opt_linit(xp,sclass);
}
if (cur->e_token == ',') {
fadvnode();
goto more;
}
if (cur->e_token == ';') {
fadvnode();
} else {
error("expect ;");
return 1;
}
}
while (STACKALN & size)
size++;
blktab->b_size = size;
blktab->b_regs = regs;
return rv;
}
/* Decls inside Struct/Union */
su_decls(listpp, isunion, sizep, alnp)
NODEP *listpp;
long *sizep;
char *alnp;
{
register NODEP head, xp;
NODEP d_type(), d_declr();
long size;
char aln;
int fldw, fldoff;
aln = 0;
size = 0;
fldoff = 0;
for(;;) {
head = d_type();
if (head == NULL)
goto out;
if (ok_suh(head) == 0)
continue;
more:
xp = d_declr(head,0);
opt_field(xp,&fldw,isunion);
if (ok_sux(xp,head)) {
if (fldw > 0) { /* handle field */
su_fld(&size,&aln,xp,fldw,&fldoff);
xp->e_offs = size;
} else { /* handle non-field */
afterfld(&size,&fldoff);
xp->e_offs = isunion ? 0 : size;
su_size(&size,&aln,xp,isunion);
}
new_sym(listpp,xp);
listpp = &xp->n_next;
} else if (fldw == 0) {
afterfld(&size, &fldoff);
}
if (cur->e_token == ',') {
fadvnode();
goto more;
}
if (cur->e_token == ';') {
fadvnode();
} else
goto out;
}
out:
afterfld(&size,&fldoff);
while (aln & size)
size++;
*sizep = size;
*alnp = aln;
return;
}
/* Decls inside Enum */
en_decls()
{
register NODEP head, xp;
NODEP bas_type(), d_declr();
int curval = 0;
for(;;) {
head = bas_type(K_INT);
more:
xp = d_declr(head,0);
if (ok_enx(xp,head)) {
opt_enval(&curval);
xp->e_ival = curval++;
xp->e_sc = ENUM_SC;
new_sym(level ? blktab->b_syms : (NODE *)symtab,
xp);
}
if (cur->e_token == ',') {
fadvnode();
goto more;
}
return;
}
}
/*
* called from expr.c, make a cast
* only called if is_ty_start();
*/
NODE *
makecast()
{
NODEP head, xp;
register NODEP np;
NODEP d_type(), d_declr(), def_type();
head = d_type(); /* we know this is not NULL */
xp = d_declr(head, 1);
if (ok_cast(xp,head) == 0) {
xp = def_type(); /* return cast to INT */
}
np = allocnode();
np->e_token = TCONV;
np->n_tptr = xp;
if (xp == head)
np->n_flags |= N_COPYT;
if (debug) {
printf("Make cast");
printnode(np);
}
return np;
}
is_ty_start()
{
NODEP rv;
if (is_tykw(cur->e_token))
return 1;
if (cur->e_token == ID) {
rv = allsyms(cur);
if (rv && rv->e_sc == K_TYPEDEF)
return 1;
}
return 0;
}
/* assemble decl and put in listpp */
new_sym(listpp, xp)
NODEP *listpp;
NODEP xp;
{
NODEP old;
if (xp == NULL)
return 0;
/* put in table */
if (debug) {
printf("New sym sc %c", "EARTSCH"[xp->e_sc-K_EXTERN]);
printnode(xp);
}
/* later look for previous definition */
if (listpp == (NODE **)symtab) {
old = hlook(listpp, xp);
if (old == NULL || def2nd(old, xp))
puthlist(listpp, xp);
} else {
old = llook(*listpp, xp);
if (old == NULL || def2nd(old, xp))
putlist(listpp, xp);
}
return 1;
}
/* look for storage class */
d_scl(defau)
{
int rv;
if (is_sclass(cur->e_token)) {
rv = cur->e_token;
fadvnode();
return rv;
}
/* no storage class specified */
return defau;
}
NODEP
d_declr(head, forcast)
NODEP head;
{
NODEP e1;
NODEP declarator(), rev_decl();
NODEP xp, tailp;
e1 = declarator();
xp = rev_decl(e1, &tailp, forcast);
if (xp) {
tailp->n_tptr = head;
tailp->n_flags |= N_COPYT;
return xp;
} else if (forcast)
return head;
else
return NULL;
}
NODEP
rev_decl(np,tailpp,forcast)
NODEP np, *tailpp;
{
NODEP rv, scan, nxt;
rv = NULL;
for (scan = np; scan != NULL; scan = nxt) {
nxt = scan->n_next;
scan->n_next = NULL;
if (rv == NULL) {
*tailpp = scan;
scan->n_tptr = NULL;
rv = scan;
} else {
scan->n_tptr = rv;
rv = scan;
}
e_to_t(rv);
switch (rv->t_token) {
case UNARY '*':
sprintf(rv->n_name, "Ptr to");
break;
case '(':
sprintf(rv->n_name, "Fun ret");
break;
case '[':
sprintf(rv->n_name, "Ary of");
break;
case ID:
break;
default:
error("bad type xpr");
return NULL;
}
}
/* if normal decl and see something, must see id first */
if (!ok_revx(rv,forcast))
rv = NULL;
return rv;
}
/*
* Looking for type part of a decl
*/
NODEP
d_type()
{
int btype, adj;
NODEP rv;
NODEP bas_type(), decl_su(), decl_enum();
/* look for 'struct', 'union', 'enum' or typedef ID */
switch (cur->e_token) {
case ID:
rv = allsyms(cur);
if (rv && rv->e_sc == K_TYPEDEF) {
fadvnode();
rv = rv->n_tptr;
return rv;
}
return NULL;
case K_STRUCT:
return decl_su(0);
case K_UNION:
return decl_su(1);
case K_ENUM:
return decl_enum();
}
/* look for modifiers 'long', 'short', 'unsigned' */
adj = 0;
while (is_tadj(cur->e_token)) {
switch (cur->e_token) {
case K_SHORT:
adj |= SAW_SHORT;
break;
case K_LONG:
adj |= SAW_LONG;
break;
case K_UNSIGNED:
adj |= SAW_UNS;
break;
}
fadvnode();
}
/* look for base type 'char', 'int', 'float', 'double', 'void'*/
if (is_btype(cur->e_token)) {
btype = cur->e_token;
fadvnode();
} else if (adj == 0) /* saw nothing */
return NULL;
else
btype = K_INT;
if (adj)
btype = adj_type(btype, adj);
rv = bas_type(btype);
return rv;
}
NODEP
decl_enum()
{
NODEP bas_type();
fadvnode(); /* skip 'enum' */
if (cur->e_token == ID) { /* ignore tag */
fadvnode();
}
if (cur->e_token == '{') { /* new declaration */
fadvnode(); /* skip '{' */
en_decls(); /* global scope */
if (cur->e_token != '}')
error("expect }");
else
fadvnode(); /* skip '}' */
}
return bas_type(K_INT);
}
extern lineno;
NODEP
decl_su(isunion)
{
register NODEP rv, tagp;
NODEP *attab;
fadvnode(); /* skip 'struct' or 'union' */
attab = level ? &blktab->b_tags : &tagtab;
tagp = NULL;
if (cur->e_token == ID) { /* hold on to ID node */
tagp = cur;
e_to_t(tagp);
advnode();
nnmadd(tagp, isunion ? ".U" : ".S");
}
if (cur->e_token == '{') { /* new declaration */
if (tagp == NULL) { /* make fake name */
tagp = allocnode();
sprintf(tagp->n_name, isunion ? "%dU" :
"%dS", lineno);
}
fadvnode(); /* skip '{' */
if (rv = llook(*attab, tagp)) {
freenode(tagp);
if (rv->n_right) {
errors("struct redefined", rv->n_name);
freenode(rv->n_right);
rv->n_right = NULL;
}
} else { /* new defn */
rv = tagp;
rv->t_token = isunion ? K_UNION : K_STRUCT;
rv->n_flags |= N_BRKPR; /* break print loops */
putlist(attab, rv);
}
su_decls(&rv->n_right, isunion,
&rv->t_size, &rv->t_aln);
if (cur->e_token != '}')
error("expect }");
else
fadvnode(); /* skip '}' */
} else { /* reference to old */
if (tagp == NULL) {
error("nonsense struct");
goto out;
}
/* ANSI special decl
struct <tag> ;
for hiding old tag within block */
if (cur->e_token == ';' && level)
rv = llook(*attab, tagp);
else
rv = alltags(tagp);
if (rv == NULL) { /* delayed tag */
rv = tagp;
rv->t_token = isunion ? K_UNION : K_STRUCT;
rv->n_flags |= N_BRKPR; /* break print loops */
putlist(attab, rv);
goto out;
} else
freenode(tagp);
}
out:
return rv;
}
NODE *
alltags(np)
NODE *np;
{
register NODE *bp;
NODE *rv;
for (bp=blktab; bp != NULL; bp = bp->n_next)
if ((rv = llook(bp->b_tags, np)) != NULL)
return rv;
return llook(tagtab, np);
}
NODE *
allsyms(np)
NODE *np;
{
register NODE *bp;
NODE *rv;
for (bp=blktab; bp != NULL; bp = bp->n_next)
if ((rv = llook(bp->b_syms, np)) != NULL)
return rv;
return hlook(symtab, np);
}
sim_type(a,b)
register NODE *a, *b;
{
more:
if (a == b)
return 1;
if (a == NULL || b == NULL)
return 0;
if (a->t_token != b->t_token)
return 0;
if (a->t_size != b->t_size && a->t_size && b->t_size)
return 0;
a = a->n_tptr;
b = b->n_tptr;
goto more;
}
/* 2nd def of same name at same level */
/* OK if one extern and types the same */
def2nd(old,new)
NODEP old, new;
{
int osc, nsc;
if (sim_type(old->n_tptr, new->n_tptr) == 0)
goto bad;
osc = old->e_sc;
nsc = new->e_sc;
if (nsc == K_EXTERN) { /* works only if no further use allowed */
freenode(new);
return 0;
}
if (osc == K_EXTERN) {
/* replace old def with new one */
/* for now, just put new one on list too */
return 1;
}
bad:
errorn("bad 2nd decl of ", new);
/* use 2nd def so other stuff works */
return 1;
}
/* saw fun but no body */
fix_fun(np)
NODE *np;
{
if (np == NULL) return;
if (np->n_tptr->t_token == '(') { /* fix to extern */
if (np->e_sc != K_TYPEDEF)
np->e_sc = K_EXTERN;
}
}
e_to_t(np)
NODE *np;
{
int token;
token = np->e_token;
np->t_token = token;
np->t_size = 0;
np->t_aln = 0;
}
SHAR_EOF
cat << \SHAR_EOF > expr.c
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* expr.c
*
* Expression parse routines
*
* All routines return either NULL or a valid tree
* binop nodes have non-null left and right
* unop nodes have non-null left
*
* Special nodes:
* '(' : function call. left:name-expr right:args
* ',': if part of function arg list, ival:num. descendants
* '?' : ?switch. left:test-expr right:':' part
* ':' : left:true-expr right:false-expr
* TCONV: left:convertee tptr:type-list
* TSIZEOF: tptr:type-list
*
*/
#include <stdio.h>
#include "param.h"
#include "nodes.h"
#include "tok.h"
extern NODEP cur;
NODEP getnode();
NODEP opt_follow();
extern int oflags[];
#define debug oflags['x'-'a']
advnode()
{
cur = getnode();
}
fadvnode()
{
freenode(cur);
cur = getnode();
}
NODEP
gete_or_ty()
{
NODEP getexpr(), makecast();
NODEP rv;
if (is_ty_start()) {
rv = makecast();
if (debug) {
printf("TY_X");
printnode(rv);
}
return rv;
} else
return getexpr();
}
/* call this for any expr including comma's */
NODEP
getexpr()
{
NODEP np, get_f_expr();
np = get_f_expr(0);
return np;
}
NODEP
get_f_expr(flg)
int flg;
{
NODEP assignx();
register NODEP op, lpart, rpart;
int i = 0;
lpart = assignx();
if (lpart == NULL) {
return NULL;
}
i++;
more:
if (cur->e_token != ',')
return lpart;
op = cur; advnode();
rpart = assignx();
if (rpart == NULL) {
error("',' expr syntax");
return lpart;
}
i++;
op->n_left = lpart;
op->n_right = rpart;
op->e_type = E_BIN;
op->e_ival = flg ? i : 0;
lpart = op;
if (debug) {
printf("COMMA");
printnode(op);
}
goto more;
}
/* call this if you want expr w/o comma's */
NODEP
assignx()
{
NODEP questx();
register NODEP op, lpart, rpart;
lpart = questx();
if (lpart == NULL)
return NULL;
if (!isassign(cur->e_token) && cur->e_token != '=')
return lpart;
op = cur; advnode();
rpart = assignx();
if (rpart == NULL) {
error("'=op' expr syntax");
return lpart;
}
op->n_left = lpart;
op->n_right = rpart;
op->e_type = E_BIN;
if (debug) {
printf("ASSIGN");
printnode(op);
}
return op;
}
/* call this if you want expr w/o assign's or comma's */
/* i.e. constant-expression */
NODEP
questx()
{
NODEP binary();
register NODEP holdq, holdc;
NODEP qpart, tpart, fpart;
qpart = binary();
if (qpart == NULL)
return NULL;
if (cur->e_token != '?')
return qpart;
holdq = cur; advnode();
tpart = questx();
if (tpart == NULL || cur->e_token != ':') {
bad:
error("'?:' expr syntax");
return qpart;
}
holdc = cur; advnode();
fpart = questx();
if (fpart == NULL) goto bad;
holdc->n_left = tpart;
holdc->n_right = fpart;
holdc->e_type = E_BIN;
holdq->n_left = qpart;
holdq->n_right = holdc;
holdq->e_type = E_BIN;
if (debug) {
printf("QUEST");
printnode(holdq);
}
return holdq;
}
NODEP
binary()
{
NODEP unary(), buildbin();
register NODEP rv, op, e2;
rv = unary();
if (rv == NULL)
return NULL;
rv->e_prec = 0;
more:
if (cur->e_prec == 0) /* not binary op */
return rv;
op = cur; advnode();
e2 = unary();
if (e2 == NULL) {
error("bin-op expr syntax");
return rv;
}
e2->e_prec = 0;
rv = buildbin(rv, op, e2);
if (debug) {
printf("BINARY");
printnode(rv);
}
goto more;
}
NODEP
buildbin(lpart, op, upart)
NODEP lpart, op, upart;
{
register NODEP look, tail;
NODEP rv;
tail = NULL;
look = lpart;
for (look=lpart; op->e_prec < look->e_prec; look=look->n_right)
tail = look;
if (tail == NULL) {
op->n_left = lpart;
op->n_right = upart;
rv = op;
} else {
tail->n_right = op;
op->n_left = look;
op->n_right = upart;
rv = lpart;
}
op->e_type = E_BIN;
return rv;
}
NODEP
unary()
{
register NODEP tp,e1;
NODEP primary();
if (cur->e_flags & CAN_U) {
tp = cur; advnode();
if (tp->e_prec) { /* also have BINARY op */
tp->e_token = UNARY tp->e_token;
strcat(tp->n_name, "U");
}
tp->n_left = unary();
tp->e_type = E_UNARY;
goto check;
} else
switch (cur->e_token) {
case '(':
fadvnode();
tp = gete_or_ty();
if (cur->e_token != ')') {
error("missing )");
} else
fadvnode();
if (tp == NULL)
return NULL;
if (tp->e_token == TCONV && tp->n_left == NULL) {
sprintf(tp->n_name, "cast to");
tp->n_left = unary();
tp->e_type = E_UNARY;
} else {
tp = opt_follow(tp);
goto out;
}
goto check;
case K_SIZEOF:
tp = cur;
advnode();
if (cur->e_token == '(') { /* may be type expr */
fadvnode();
e1 = gete_or_ty();
if (cur->e_token != ')') {
error("missing )");
} else
fadvnode();
} else
e1 = unary();
if (e1 == NULL) {
error("sizeof expr syntax");
return NULL;
}
if (e1->e_token == TCONV) {
freeunit(tp);
e1->e_token = TSIZEOF;
sprintf(e1->n_name, "T-sizeof");
tp = e1;
tp->e_type = E_LEAF;
goto out;
} else {
tp->e_type = E_UNARY;
tp->n_left = e1;
}
goto check;
default:
tp = primary();
goto out;
}
check:
if (tp == NULL) return NULL;
if (tp->n_left == NULL) {
error("u-op expr syntax");
return NULL;
}
out:
if (debug) {
printf("UNARY");
printnode(tp);
}
return tp;
}
NODEP
primary()
{
register NODEP e1;
switch (cur->e_token) {
case ID:
case ICON:
case FCON:
case SCON:
e1 = cur;
e1->e_type = E_LEAF;
advnode();
break;
case '(':
fadvnode();
e1 = getexpr();
if (cur->e_token != ')')
error("missing )");
else
fadvnode();
break;
default:
e1 = NULL;
}
if (e1 == NULL)
return NULL;
return opt_follow(e1);
}
NODEP
opt_follow(np)
NODEP np;
{
register NODEP tp, e1, t2;
switch (cur->e_token) {
case '[':
tp = cur; advnode();
e1 = getexpr();
if (cur->e_token != ']') {
error("missing ]");
return np;
} else {
t2 = cur; advnode();
}
if (e1 == NULL) {
error("empty []");
return np;
}
t2->n_left = np;
t2->n_right = e1;
t2->e_type = E_BIN;
t2->e_token = '+';
strcpy(t2->n_name, "+ [");
tp->n_left = t2;
tp->e_type = E_UNARY;
tp->e_token = STAR;
strcpy(tp->n_name, "U*");
goto out;
case '(':
tp = cur;
advnode();
e1 = get_f_expr(1);
if (cur->e_token != ')')
error("expect )");
else
fadvnode();
tp->n_left = np;
tp->n_right = e1;
tp->e_type = E_SPEC;
goto out;
case '.':
case ARROW:
tp = cur; advnode();
if (cur->e_token != ID) {
error("expect ID");
return np;
}
tp->n_left = np;
tp->n_right = cur;
tp->e_type = E_SPEC;
if (tp->e_token == ARROW) { /* make into (*X).Y */
tp->e_token = '.';
strcpy(tp->n_name, ".");
t2 = allocnode();
t2->e_token = STAR;
t2->n_left = np;
t2->e_type = E_UNARY;
strcpy(t2->n_name, "U*");
tp->n_left = t2;
}
advnode();
goto out;
case DOUBLE '+':
case DOUBLE '-':
tp = cur; advnode();
tp->e_token = (tp->e_token == DOUBLE '+') ? POSTINC : POSTDEC;
strcat(tp->n_name, "post");
tp->n_left = np;
tp->e_type = E_UNARY;
goto out;
default:
return np;
}
out:
return opt_follow(tp);
}
/* restricted version of unary for declarations or coertions */
/* allows NULL primary part */
NODEP
declarator()
{
register NODEP tp,e1;
NODEP ty_primary(), ty_follow();
if (cur->e_token == '*') {
tp = cur;
tp->e_token = UNARY tp->e_token;
strcat(tp->n_name, "U");
advnode();
tp->n_left = declarator();
return tp;
} else
switch (cur->e_token) {
case '(':
tp = cur;
advnode();
e1 = declarator();
if (cur->e_token != ')') {
error("expect )");
} else
fadvnode();
if (e1 == NULL) { /* special "fun of" */
/* left and right already NULL */
return ty_follow(tp);
} else {
freeunit(tp);
return ty_follow(e1);
}
default:
return ty_primary();
}
}
/* restricted version of primary for "declarator" */
NODEP
ty_primary()
{
register NODEP e1;
NODEP ty_follow();
switch (cur->e_token) {
case ID:
e1 = cur;
advnode();
break;
case '(':
fadvnode();
e1 = declarator();
if (cur->e_token != ')')
error("expect )");
else
fadvnode();
break;
default:
e1 = NULL;
}
return ty_follow(e1);
}
/* restricted version of opt_follow for 'declarator' */
/* allow null [] */
NODEP
ty_follow(np)
NODEP np;
{
register NODEP tp, e1;
NODEP ty_args();
switch (cur->e_token) {
case '[':
tp = cur;
advnode();
e1 = questx();
if (cur->e_token != ']')
error("expect ]");
else
fadvnode();
tp->n_left = np;
tp->n_right = e1;
goto out;
case '(':
tp = cur;
advnode();
e1 = ty_args(); /* allow args of fun to follow */
if (cur->e_token != ')')
error("expect )");
else
fadvnode();
tp->n_left = np;
tp->n_right = e1;
goto out;
default:
return np;
}
out:
return ty_follow(tp);
}
/* called for args of function declaration or NULL */
NODEP
ty_args()
{
NODEP opt_id();
register NODEP rv, tail, new;
rv = opt_id();
if (rv == NULL)
return NULL;
tail = rv;
more:
if (cur->e_token != ',')
return rv;
fadvnode();
new = opt_id();
if (new == NULL) {
error("expect as-op value");
return rv;
}
tail->n_left = new;
tail = new;
goto more;
}
NODEP
opt_id()
{
NODEP rv;
if (cur->e_token == ID) {
rv = cur;
advnode();
return rv;
} else
return NULL;
}
SHAR_EOF
cat << \SHAR_EOF > fix.c
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* fix.c
*
* Motorola has is not consistent in what operations allow
* which operands. This section compensates for that --
* tries to find the best way to do something.
*/
#include <stdio.h>
#include "param.h"
#include "nodes.h"
#include "flags.h"
#include "bstok.h"
#include "gen.h"
#include "ops.h"
#define FAIL 0
#define OKAY 1
#define CL_IMM IOPD
#define CL_AREG AOPD
#define CL_DREG DOPD
#define CL_ADR MOPD
#define RETAREG 0x100
#define RETDREG 0x200
#define RETLEFT 0x400
#define RETRIGHT 0x800
#define LISTMP 1
#define RISTMP 2
#define NDASSOC 4
#define CANRL 8
#define CANLR 0x10
#define CANRD 0x20
#define CANDL 0x40
#define CANLD 0x80
#define CANDD 0x100
#define CANDR 0x200
struct mtbl {
int restr;
char *code;
int needregs;
} tbl2[] = {
{LISTMP|CANRL,
"\tN.S\t>A,<A\n", RETLEFT},
{RISTMP|CANLR|NDASSOC,
"\tN.S\t<A,>A\n", RETRIGHT},
{CANRD,
"\tmove.S\t<A,A\n\tN.S\t>A,A\n", RETDREG},
{CANLD|NDASSOC,
"\tmove.S\t>A,A\n\tN.S\t<A,A\n", RETDREG},
/* only EOR and shifts get to here */
{CANDL|LISTMP,
"\tmove.S\t>A,R1\n\tN.S\tR1,A\n", RETLEFT|1},
{CANDR|RISTMP|NDASSOC,
"\tmove.S\t<A,R1\n\tN.S\tR1,A\n", RETRIGHT|1},
{CANDD,
"\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n",
RETDREG|1},
{0}
};
struct mtbl tblmul[] = {
{CANRL|LISTMP,
"\tmulU\t>A,<A\n", RETLEFT},
{CANLR|RISTMP,
"\tmulU\t<A,>A\n", RETRIGHT},
{CANRD,
"\tmove.w\t>A,A\n\tmulU\t<A,A\n", RETDREG},
{0}
};
struct mtbl tbldiv[] = {
{CANRL|LISTMP,
"\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT},
{CANRD,
"\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n", RETDREG},
{0}
};
struct mtbl tbludiv[] = {
{CANRD,
"\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n", RETDREG},
{0}
};
struct mtbl tblc[] = {
{CANRL,
"\tcmp.<S\t>A,<A\n", 0},
{CANRD,
"\tmove.<S\t<A,R1\n\tcmp.<S\t>A,R1\n", 1},
/* shouldnt get to here! */
{CANDL,
"\tmove.<S\t>A,R1\n\tcmp.<S\tR1,<A\n", 1},
{CANDD,
"\tmove.<S\t>A,R1\n\tmove.<S\t<A,R2\n\tcmp.<S\tR1,R2\n", 2},
{0}
};
struct mtbl tblas[] = {
{CANRL,
"\tN.S\t>A,<A\n", RETLEFT},
{CANDL,
"\tmove.S\t>A,R1\n\tN.S\tR1,A\n", 1|RETLEFT},
/* only MUL, DIV and shifts should get to here */
{CANRD,
"\tmove.S\t<A,A\n\tN.S\t>A,A\n\tmove.S\tA,<A\n",
RETDREG},
{CANLD|NDASSOC,
"\tmove.S\t>A,A\n\tN.S\t<A,A\n\tmove.S\tA,<A\n",
RETDREG},
{CANDD,
"\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n\tmove.S\tA,<A\n",
RETDREG|1},
{0}
};
struct mtbl tblamul[] = {
{CANRL,
"\tmulU\t>A,<A\n", RETLEFT},
{CANLR|RISTMP,
"\tmulU\t<A,>A\n\tmove.w\t>A,<A\n", RETRIGHT},
{CANRD,
"\tmove.w\t<A,A\n\tmulU\t>A,A\n\tmove.w\tA,<A\n", RETDREG},
{0}
};
struct mtbl tbladiv[] = {
{CANRL,
"\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT},
{CANRD,
"\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tmove.w\tA,<A\n",
RETDREG},
{0}
};
struct mtbl tbluadiv[] = {
{CANRD,
"\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tmove.w\tA,<A\n",
RETDREG},
{0}
};
struct mtbl tblamod[] = {
{CANRL,
"\text.l\t<A\n\tdivs\t>A,<A\n\tswap\t<A\n", RETLEFT},
{CANRD,
"\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n",
RETDREG},
{0}
};
struct mtbl tbluamod[] = {
{CANRD,
"\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n",
RETDREG},
{0}
};
class(np)
NODEP np;
{
switch (np->g_token) {
case ICON:
return CL_IMM;
case ONAME:
return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR;
case OREG:
return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR;
case PUSHER:
return CL_ADR;
case REGVAR:
if (np->g_rno < AREG)
return CL_DREG;
else
return CL_AREG;
default:
printf("Weird class ");
return CL_IMM;
}
}
int canswap;
NODEP matchnp;
fix_cmp(np, flags)
NODEP np;
{
NODEP rp = np->n_right;
/* special stuff for ICON 0 */
if (rp->g_token == ICON && rp->g_offs == 0 &&
(rp->g_flags & IMMEDID)) {
addcode(np, "<Q");
return OKAY;
}
canswap = 0;
return fix_sub(np, flags, tblc);
}
fix2ops(np, flags)
NODEP np;
{
canswap = flags & ASSOC;
return fix_sub(np, flags, tbl2);
}
fixmul(np, flags)
NODEP np;
{
return fix_sub(np, flags, tblmul);
}
fixdiv(np, flags)
NODEP np;
{
return fix_sub(np, flags, np->g_ty == ET_U ? tbludiv : tbldiv);
}
fixmod(np, flags)
NODEP np;
{
int r;
r = fixdiv(np, flags);
addcode(np, "\tswap\tA\n");
return r;
}
fixamul(np, flags)
NODEP np;
{
return fix_sub(np, flags, tblamul);
}
fixadiv(np, flags)
NODEP np;
{
return fix_sub(np, flags, np->g_ty == ET_U ? tbluadiv : tbladiv);
}
fixamod(np, flags)
NODEP np;
{
return fix_sub(np, flags, np->g_ty == ET_U ? tbluamod : tblamod);
}
fix_asn(np, flags)
NODEP np;
{
canswap = 0;
return fix_sub(np, flags, tblas);
}
fix_sub(np, flags, tbl)
register NODEP np;
struct mtbl *tbl;
{
NODEP lp = np->n_left, rp = np->n_right;
int lclass, rclass;
register struct mtbl *p;
int rv;
lclass = class(lp);
rclass = class(rp);
matchnp = np;
for (p = tbl; p->restr; p++)
if ((rv = cando(flags, p->restr, lclass, rclass))) {
dotbl(p, np);
return OKAY;
}
printf("no code table match! ");
return FAIL;
}
dotbl(p, np)
struct mtbl *p;
NODEP np;
{
register int i, k;
if (p->needregs) {
i = p->needregs;
if (i & RETLEFT)
inherit(np);
else if (i & RETRIGHT)
rinherit(np);
else if (i & RETAREG)
retreg(np, ralloc(AREG));
else if (i & RETDREG)
retreg(np, ralloc(0));
k = i & 7;
while (k--)
tempr(np, 0);
k = (i/AREG) & 7;
while (k--)
tempr(np, AREG);
}
addcode(np, p->code);
}
#define canflag(l,r) (l << cansh[r])
short cansh[] = {0, 0, 4, 0, 8, 0, 0, 0, 12};
cando(flags, restr, lc, rc)
register restr;
{
NODEP lp = matchnp->n_left, rp = matchnp->n_right;
if (restr & RISTMP) {
if ((rc & (CL_DREG|CL_AREG)) == 0 ||
istemp(rp->g_rno) == 0)
return 0;
} else if (restr & LISTMP) {
if ((lc & (CL_DREG|CL_AREG)) == 0 ||
istemp(lp->g_rno) == 0)
return 0;
}
if (restr & NDASSOC) {
if (canswap == 0)
return 0;
}
if (restr & (CANLR|CANLD)) {
flags |= quickflag(lp, flags);
} else if (restr & (CANRL|CANRD)) {
flags |= quickflag(rp, flags);
}
flags &= 0xfff;
if (restr & CANLR) {
if ((flags & canflag(lc,rc)) == 0)
return 0;
} else if (restr & CANRL) {
if ((flags & canflag(rc,lc)) == 0)
return 0;
} else if (restr & CANRD) {
if ((flags & canflag(rc,CL_DREG)) == 0)
return 0;
} else if (restr & CANDL) {
if ((flags & canflag(CL_DREG,lc)) == 0)
return 0;
} else if (restr & CANLD) {
if ((flags & canflag(lc,CL_DREG)) == 0)
return 0;
} else if (restr & CANDR) {
if ((flags & canflag(CL_DREG,rc)) == 0)
return 0;
} else if (restr & CANDD) {
if ((flags & DOPD) == 0)
return 0;
}
return 1;
}
quickflag(np, flags)
NODEP np;
{
long offs;
if (np->g_token != ICON)
return 0;
offs = np->g_offs;
if ((flags & QOPD) && np->g_offs >= 1 && np->g_offs <= 8)
return IOPD;
if ((flags & ONEOPM) && np->g_offs == 1)
return IOPM;
return 0;
}
/*
* stuff to do field extract and field assign
* Yes, this stuff can be optimized a lot more ... feel free
*/
fldget(np, flags)
register NODEP np;
{
int how;
how = 1;
if (np->g_fldo == 0)
how = 0; /* no shift needed */
else if (np->g_fldo > 8)
how = 2; /* shift too big for immediate */
np->n_left->g_offs += np->g_offs; /* major HACK, hope it works */
retreg(np, ralloc(0));
addcode(np, "\tmove\t<A,A\n"); /* get word */
if (how) /* shift to position */
addcode(np, how==1 ? "\tlsr\t#Y,A\n" :
"\tlsr\t#8,A\n\tlsr\t#Z,A\n");
addcode(np, "\tand\t#W,A\n"); /* mask off top */
return OKAY;
}
fldasn(np, flags)
register NODEP np;
{
int how;
how = 1;
if (np->g_fldo == 0)
how = 0; /* no shift needed */
else if (np->g_fldo > 8)
how = 2; /* shift too big for immediate */
retreg(np, ralloc(0));
tempr(np, 0);
addcode(np, "\tmove\t>A,A\n"); /* value */
if (needmask(np)) /* mask off high bits */
addcode(np, "\tand\t#W,A\n");
if (how) /* shift into position */
addcode(np, how==1 ? "\tlsl\t#Y,A\n" :
"\tlsl\t#8,A\n\tlsl\t#Z,A\n");
addcode(np, "\tmove\t<A,R1\n"); /* old value */
addcode(np, "\tand\t#X,R1\n"); /* mask out old value */
addcode(np, "\tor\tA,R1\n"); /* set new field */
addcode(np, "\tmove\tR1,<A\n"); /* store new word */
if (how && (flags & NOVAL_OK) == 0) /* return value */
addcode(np, how==1 ? "\tlsr\t#Y,A\n" :
"\tlsr\t#8,A\n\tlsr\t#Z,A\n");
return OKAY;
}
needmask(np)
register NODEP np;
{
NODEP lp = np->n_left;
if (np->g_fldw + np->g_fldo >= 16)
return 0;
if (lp->g_token != ICON)
return 1;
if ((int)lp->g_offs & ~ones(np->g_fldw)) {
warn("value too big for field");
return 1;
}
return 0;
}
SHAR_EOF
cat << \SHAR_EOF > fun.c
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* fun.c
*
* Handle function entry, exit, etc.
* Parse statements.
* Also, general syntax error recovery strategy.
*/
#include <stdio.h>
#include "param.h"
#include "tok.h"
#include "nodes.h"
#include "cookie.h"
#if MMCC
overlay "pass2"
#endif
extern NODE *cur;
int level;
NODE *blktab;
NODE *labels;
struct swittbl {
NODEP caselist;
int deflbl;
} *curswit;
int curbrk, curcont;
int funtopl, funbotl, funretl, funstrl;
NODEP funtyp;
int maxregs;
long maxlocs;
int skipon;
NODEP glb_decls();
extern int oflags[];
#define debugl oflags['l'-'a']
#define debugs oflags['s'-'a']
#define debugv oflags['v'-'a']
findtok(x)
{
while (cur->e_token != EOFTOK && cur->e_token != x)
fadvnode();
if (cur->e_token == EOFTOK)
exit(1);
}
extern NODEP symtab[];
program()
{
NODEP last;
skipon = 0;
more:
last = glb_decls();
if (cur->e_token == EOFTOK)
return;
if (last) skipon = 0; /* saw something valid */
if (last && last->n_tptr && last->n_tptr->t_token == '(') {
/* possible function definition */
if (debugs) {
printf("FUN ");
put_nnm(last);
}
out_fstart(last);
last->e_sc = K_EXTERN;
fun_start(last->n_tptr);
args_blk(last->n_tptr->n_right);
sub_block();
fun_end();
clr_lvl(); /* for args block */
goto more;
}
/* error if get to here */
if (last) {
error("missing ;");
goto more;
} else {
skip();
goto more;
}
}
fun_start(np)
NODEP np;
{
NODEP functy();
funtyp = functy(np);
curbrk = curcont = -1;
funtopl = new_lbl();
funbotl = new_lbl();
funretl = new_lbl();
switch (funtyp->t_token) {
case K_STRUCT:
case K_UNION:
funstrl = new_lbl();
break;
default:
funstrl = 0;
}
maxregs = 0;
maxlocs = 0;
out_br(funbotl);
def_lbl(funtopl);
}
fun_end()
{
NODEP np;
if (labels) {
for (np = labels; np; np = np->n_next)
if (np->c_defined == 0)
errorn("undefined label", np);
freenode(labels);
labels = NULL;
}
def_lbl(funretl);
out_fret(maxregs, funstrl);
def_lbl(funbotl);
out_fend(maxregs, maxlocs);
out_br(funtopl);
if (funstrl)
out_fs(funstrl, funtyp->t_size);
}
skip()
{
if (skipon == 0) {
error("syntax (try skipping...)");
skipon = 1;
}
fadvnode();
}
block()
{
int some;
int sawsome;
some = loc_decls();
if (cur->e_token == EOFTOK)
return;
if (some) skipon = 0;
more:
sawsome = stmts();
if (sawsome) skipon = 0;
if (cur->e_token == '}') {
if (blktab->b_regs > maxregs)
maxregs = blktab->b_regs;
if (blktab->b_size + blktab->b_tsize > maxlocs)
maxlocs = blktab->b_size + blktab->b_tsize;
return;
}
/* error if get to here */
if (cur->e_token == EOFTOK || is_tykw(cur->e_token))
/* get out of block */
return;
else {
skip();
goto more;
}
}
clr_lvl()
{
NODE *bp;
level--;
bp = blktab;
blktab = bp->n_next;
bp->n_next = NULL;
if (debugl && bp->b_syms) {
printf("local syms %d", level);
printlist(bp->b_syms);
}
freenode(bp->b_syms);
if (debugl && bp->b_tags) {
printf("local tags %d", level);
printlist(bp->b_tags);
}
freenode(bp->b_tags);
freenode(bp);
}
eat(c)
{
char *p = "assume X";
if (cur->e_token == c)
fadvnode();
else {
p[strlen(p) - 1] = c;
error(p);
}
}
sub_block()
{
register NODE *new;
if (debugs)
printf("{ ");
eat('{');
level++;
new = allocnode();
new->n_next = blktab;
sprintf(new->n_name, "sub{");
blktab = new;
block();
clr_lvl();
eat('}');
if (debugs)
printf("}\n");
}
args_blk(np)
NODEP np;
{
register NODE *p;
register NODE *new;
NODE *tp;
NODEP llook();
long size;
int rmask;
size = 0;
rmask = 0;
new = allocnode();
new->n_next = blktab;
sprintf(new->n_name, "arg{");
blktab = new;
level++;
loc_decls();
/* make sure all decls were in arg list */
for (p=new->b_syms; p != NULL; p = p->n_next)
if (llook(np, p) == NULL)
errorn("ID not param", p);
/* now make any names not mentioned INT */
/* and generate offsets and alloc regs */
for (p=np; p != NULL; p = p->n_next) {
if ((tp=llook(new->b_syms, p)) == NULL) {
def_arg(&new->b_syms, p);
tp = new->b_syms;
}
lc_size(&size, &rmask, tp);
if (tp->e_sc == K_REGISTER)
reg_arg(&rmask, tp);
if (debugv) {
printf("final o%ld r%d ", tp->e_offs, tp->e_rno);
put_nnm(tp);
putchar('\n');
}
}
new->b_regs = rmask;
}
reg_arg(rp, xp)
int *rp;
NODEP xp;
{
if (lc_reg(rp, xp) == 0) { /* out of regs? */
xp->e_sc = K_AUTO;
return;
}
out_argreg(xp);
}
stmts()
{
int didsome;
didsome = 0;
while (stmt())
didsome++;
return didsome;
}
stmt_bc(brk,cont)
{
int svb, svc;
svb = curbrk;
svc = curcont;
curbrk = brk;
curcont = cont;
stmt();
curbrk = svb;
curcont = svc;
}
stmt_b(brk)
{
int svb;
svb = curbrk;
curbrk = brk;
stmt();
curbrk = svb;
}
/* do a single statement */
stmt()
{
register tok;
NODEP np;
NODEP getexpr();
int i;
more:
tok = cur->e_token;
if (is_stkw(tok)) {
if (is_blkst(tok)) {
i = blk_stmt();
} else if (is_brast(tok)) {
i = bra_stmt();
} else if (is_lblst(tok)) {
i = lbl_stmt();
} else
i = asm_stmt();
if (i == 0)
goto more;
return 1;
}
else if (tok == '{') {
sub_block();
return 1;
} else if (tok == ';') {
fadvnode();
return 1;
}
np = getexpr();
if (np) {
if (cur->e_token == ':') {
fadvnode();
label(np);
goto more;
}
expr_stmt(np);
if (cur->e_token != ';')
error("missing ;");
else
fadvnode();
return 1;
}
return 0;
}
expr_stmt(np)
NODEP np;
{
if (debugs) {
printf("E_STMT ");
if (debugs > 1)
printnode(np);
}
do_expr(np, FORSIDE);
}
label(np)
NODEP np;
{
register NODEP tp;
NODEP llook();
if (debugs) {
printf("LABEL ");
if (debugs > 1)
printnode(np);
}
if (np->e_token != ID) {
error("weird label");
return;
}
tp = llook(labels, np);
if (tp) {
freenode(np);
if (tp->c_defined) {
error("duplicate label");
return;
}
} else {
putlist(&labels, np);
tp = np;
tp->c_casel = new_lbl();
}
tp->c_defined = 1;
def_lbl(tp->c_casel);
}
extern int lineno;
blk_stmt()
{
register tok;
int l1, l2, l3;
NODEP e1, e2, e3;
NODEP opt_expr(), paren_expr(), def_type();
struct swittbl locswit, *oldp;
int svline, svline2;
tok = cur->e_token;
fadvnode();
switch (tok) {
case K_IF:
if (debugs)
printf("IF ");
l1 = new_lbl();
e1 = paren_expr();
gen_brf(e1, l1);
eat(')');
stmt();
opt_else(l1);
return 1;
case K_WHILE:
if (debugs)
printf("WHILE ");
e1 = paren_expr();
l1 = new_lbl();
l2 = new_lbl();
def_lbl(l1);
gen_brf(e1,l2);
eat(')');
stmt_bc(l2,l1);
out_br(l1);
def_lbl(l2);
return 1;
case K_DO:
if (debugs)
printf("DO ");
l1 = new_lbl();
l2 = new_lbl();
l3 = new_lbl();
def_lbl(l1);
stmt_bc(l3,l2);
def_lbl(l2);
eat(K_WHILE);
e1 = paren_expr();
gen_brt(e1, l1);
eat(')');
eat(';');
def_lbl(l3);
return 1;
case K_FOR:
if (debugs)
printf("FOR ");
l1 = new_lbl();
l2 = new_lbl();
l3 = new_lbl();
eat('(');
e1 = opt_expr();
expr_stmt(e1);
eat(';');
def_lbl(l1);
e2 = opt_expr();
if (e2)
gen_brf(e2,l3);
eat(';');
e3 = opt_expr(); /* save for later */
svline = lineno;
eat(')');
stmt_bc(l3,l2);
def_lbl(l2);
svline2 = lineno;
lineno = svline;
expr_stmt(e3);
lineno = svline2;
out_br(l1);
def_lbl(l3);
return 1;
case K_SWITCH:
if (debugs)
printf("SWITCH ");
e1 = paren_expr();
l1 = new_lbl();
l2 = new_lbl();
to_d0(e1, def_type());
eat(')');
out_br(l2);
oldp = curswit;
curswit = &locswit;
locswit.caselist = NULL;
locswit.deflbl = -1;
stmt_b(l1);
out_br(l1);
def_lbl(l2);
gen_switch(locswit.caselist, locswit.deflbl);
curswit = oldp;
def_lbl(l1);
return 1;
case K_ELSE:
error("unexpected 'else'");
fadvnode();
return 0;
}
}
NODEP
paren_expr()
{
NODEP np;
NODEP need_expr();
eat('(');
np = need_expr();
return np;
}
bra_stmt()
{
register tok;
NODEP np, tp;
NODEP opt_expr(), llook();
tok = cur->e_token;
fadvnode();
switch (tok) {
case K_BREAK:
if (debugs)
printf("BRK");
eat(';');
out_br(curbrk);
return 1;
case K_CONTINUE:
if (debugs)
printf("CONT ");
eat(';');
out_br(curcont);
return 1;
case K_RETURN:
if (debugs)
printf("RETURN ");
np = opt_expr();
if (np) {
if (funstrl)
ret_stru(np);
else
to_d0(np, funtyp);
}
out_br(funretl);
eat(';');
return 1;
case K_GOTO:
if (debugs)
printf("GOTO ");
np = cur; advnode();
if (np->e_token != ID)
error("bad goto");
else {
tp = llook(labels, np);
if (tp) {
freenode(np);
} else {
tp = np;
putlist(&labels, tp);
tp->c_casel = new_lbl();
}
out_br(tp->c_casel);
}
eat(';');
return 1;
}
}
lbl_stmt()
{
register tok;
NODEP need_expr(), np;
int l1, i;
l1 = new_lbl();
tok = cur->e_token;
again:
fadvnode();
switch (tok) {
case K_CASE:
if (debugs)
printf("CASE ");
np = need_expr();
i = conxval(np);
add_case(i,l1);
eat(':');
break;
case K_DEFAULT:
if (debugs)
printf("DEFAULT ");
if (curswit->deflbl >= 0)
error("multiple 'default'");
curswit->deflbl = l1;
eat(':');
}
tok = cur->e_token; /* lookahead for more cases */
if (tok == K_CASE || tok == K_DEFAULT)
goto again;
def_lbl(l1);
return 0;
}
asm_stmt()
{
NODEP np, getexpr();
fadvnode();
np = getexpr();
if (np == NULL || np->e_token != SCON) {
error("bad asm() func");
} else {
out_asm(np);
freenode(np);
}
eat(';');
}
NODEP
opt_expr()
{
NODE *np, *getexpr();
np = getexpr();
if (np) {
if (debugs) {
printf("OXPR ");
if (debugs > 1)
printnode(np);
}
}
return np;
}
NODEP
need_expr()
{
NODE *np, *getexpr();
np = getexpr();
if (np) {
if (debugs) {
printf("NXPR ");
if (debugs > 1)
printnode(np);
}
} else
error("need expr");
return np;
}
opt_else(l1)
{
int l2;
if (cur->e_token == K_ELSE) {
if (debugs)
printf("ELSE ");
fadvnode();
l2 = new_lbl();
out_br(l2);
def_lbl(l1);
stmt();
def_lbl(l2);
} else
def_lbl(l1);
}
add_case(val, lbl)
{
NODEP np, last, p;
np = allocnode();
np->c_casev = val;
np->c_casel = lbl;
sprintf(np->n_name, "%d:%d", val, lbl);
last = NULL;
for (p = curswit->caselist; p; last=p, p=p->n_next)
if (p->c_casev == val) {
error("duplicate case");
return;
} else if (p->c_casev > val)
break;
if (last) {
last->n_next = np;
np->n_next = p;
} else {
curswit->caselist = np;
np->n_next = p;
}
if (debugs) {
printf("CASELIST\n");
printnode(curswit->caselist);
}
}
to_d0(np, typ)
NODEP np, typ;
{
NODEP tp;
tp = allocnode();
tp->e_token = TCONV;
tp->n_tptr = typ;
tp->n_flags |= N_COPYT;
tp->n_left = np;
tp->e_type = E_UNARY;
strcpy(tp->n_name, "r cast");
do_expr(tp, IND0);
}
ret_stru(np)
NODEP np;
{
p2_expr(&np);
if (same_type(np->n_tptr, funtyp) == 0) {
error("bad struct return type");
return;
}
genx(np, RETSTRU);
}
SHAR_EOF
cat << \SHAR_EOF > g2.c
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* g2.c
*
* Generate code for binary nodes.
*/
#include <stdio.h>
#include "param.h"
#include "nodes.h"
#include "flags.h"
#include "bstok.h"
#include "gen.h"
#include "ops.h"
#define FAIL 0
#define OKAY 1
extern int cookflags[];
#define isimmed(np) ((np)->g_flags & IMMEDID)
#define isareg(np) ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
struct bop {
char *s_op, *u_op;
int opflags;
} bops[] = {
{"muls", "mulu", EOPD |ASSOC},
{"divs", "divu", EOPD},
{"divs", "divu", EOPD},
{"and", "and", EOPD|DOPE|IOPE |ASSOC},
{"or", "or", EOPD|DOPE|IOPE |ASSOC},
{"eor", "eor", DOPE|IOPE |ASSOC},
{"add", "add", EOPD|DOPE|EOPA|IOPE|AOPA|AOPD |ASSOC},
{"sub", "sub", EOPD|DOPE|EOPA|IOPE|AOPA|AOPD},
{"asl", "lsl", DOPD|QOPD|ONEOPM},
{"asr", "lsr", DOPD|QOPD|ONEOPM},
};
char *tstnm[] = {
"lt", /* < */
"gt", /* > */
"le", /* <= */
"ge", /* >= */
"eq", /* == */
"ne", /* != */
};
int tstx[] = {
B_LT, B_GT, B_LE, B_GE, B_EQ, B_NE
};
char *utstnm[] = {
"cs", /* < */
"hi", /* > */
"ls", /* <= */
"cc", /* >= */
"eq", /* == */
"ne", /* != */
};
int utstx[] = {
B_ULT, B_UGT, B_ULE, B_UGE, B_EQ, B_NE
};
b_eval(np, cookie)
register NODEP np;
{
NODEP lp = np->n_left, rp = np->n_right;
NODEP tp;
int lcook = FORADR, rcook = FORADR;
switch (np->g_token) { /* special cookies */
case DOUBLE '&':
case DOUBLE '|':
lcook = rcook = FORCC;
break;
case '?':
lcook = FORCC;
break;
case '(':
rcook = FORPUSH;
break;
case ',':
if (np->g_offs) /* function args */
lcook = rcook = FORPUSH;
else {
lcook = FORSIDE;
rcook = cookie;
}
break;
case '=':
rcook = FORIMA;
break;
case '+':
case '-':
tp = rp;
while (tp->g_token == TCONV && tp->g_ty != ET_F)
tp = tp->n_left;
if (tp->g_token == ICON)
lcook = FORIMA;
break;
}
if (np->g_type == EV_LR) {
if (eval(lp,lcook) == FAIL)
return FAIL;
freetmps(lp);
if (eval(rp,rcook) == FAIL)
return FAIL;
freetmps(rp);
} else if (np->g_type == EV_RL) {
if (eval(rp,rcook) == FAIL)
return FAIL;
freetmps(rp);
if (eval(lp,lcook) == FAIL)
return FAIL;
freetmps(lp);
} else { /* EV_LRSEP */
if (eval(lp,lcook) == FAIL)
return FAIL;
freetmps(lp);
free1(NULL, lp);
if (eval(rp,rcook) == FAIL)
return FAIL;
freetmps(rp);
}
return b_sube(np, cookflags[cookie]);
}
b_sube(np, flags)
register NODEP np;
{
NODEP lp = np->n_left, rp = np->n_right;
register int i, r;
int argsize;
char buf[40];
if (isassign(np->g_token))
return as_eval(np);
switch (np->g_token) {
case '=':
if (specasn(np, flags) || strasn(np))
return OKAY;
inherit(np);
addcode(np, "\tmove.S\t>A,<A\n");
return OKAY;
case '(':
argsize = argmod(rp);
free1(NULL,rp);
if (np->g_ty == ET_A) { /* struct returned */
frc_ral(AREG);
indir(np, AREG);
} else {
frc_ral(0);
retreg(np, 0);
}
externfuncref(np);
sprintf(buf, "\tjsr\t<A\n\tadd.w\t#%d,sp\n", argsize);
addcode(np, buf);
return OKAY;
case ',':
if (np->g_offs == 0) /* normal ',' */
rinherit(np);
return OKAY;
case DOUBLE '&':
free1(NULL, rp);
r = ralloc(0);
retreg(np, r);
holdlbls(np);
np->g_betw = iscc(lp) ? "<FL1\n" :
"<Q\tbeq\tL1\n";
addcode(np, iscc(rp) ? ">FL1\n" :
">Q\tbeq\tL1\n");
addcode(np, "\tmoveq\t#1,A\n");
addcode(np, "\tbra\tL2\nL1:\tclr\tA\nL2:\n");
return OKAY;
case DOUBLE '|':
free1(NULL, rp);
r = ralloc(0);
retreg(np, r);
holdlbls(np);
np->g_betw = iscc(lp) ? "<TL1\n" :
"<Q\tbne\tL1\n";
addcode(np, iscc(rp) ? ">TL1\n" :
">Q\tbne\tL1\n");
addcode(np, "\tclr\tA\n");
addcode(np, "\tbra\tL2\nL1:\tmoveq\t#1,A\nL2:\n");
return OKAY;
case '?':
rinherit(np);
rinhlbls(np);
np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n";
return OKAY;
case ':':
free1(NULL, rp);
r = ralloc(0);
retreg(np, r);
holdlbls(np);
np->g_betw = same_a(np, lp) ?
"\tbra\tL2\nL1:\n" :
"\tmove.S\t<A,A\n\tbra\tL2\nL1:\n";
if (!same_a(np, rp))
addcode(np, "\tmove.S\t>A,A\n");
addcode(np, "L2:\n");
return OKAY;
case '<':
i = 0; goto dotst;
case '>':
i = 1; goto dotst;
case LTEQ:
i = 2; goto dotst;
case GTEQ:
i = 3; goto dotst;
case DOUBLE '=':
i = 4; goto dotst;
case NOTEQ:
i = 5;
dotst:
fix_cmp(np, EOPD|EOPA|IOPE|AOPA|AOPD);
if (flags & CC_OK) {
np->g_token = (lp->g_ty == ET_U ?
utstx[i] : tstx[i]) + BR_TOK;
} else {
strcpy(np->n_name, lp->g_ty == ET_U ?
utstnm[i] : tstnm[i]);
r = ralloc(0);
retreg(np, r);
addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
}
return OKAY;
case '*':
return fixmul(np, bops[0].opflags);
case '/':
return fixdiv(np, bops[1].opflags);
case '%':
return fixmod(np, bops[2].opflags);
case '&': i = 3; goto doop;
case '|': i = 4; goto doop;
case '^': i = 5; goto doop;
case '+':
if (optadd(np, flags, 1))
return OKAY;
i = 6; goto doop;
case '-':
if (optadd(np, flags, -1))
return OKAY;
i = 7; goto doop;
case DOUBLE '<':i = 8; goto doop;
case DOUBLE '>':i = 9;
doop:
strcpy(np->n_name, np->g_ty == ET_U ?
bops[i].u_op : bops[i].s_op);
r = fix2ops(np, bops[i].opflags);
cc_hack(np);
return r;
case FIELDAS:
return fldasn(np, flags);
default:
printf("Weird b_eval %s ", np->n_name);
return FAIL;
}
}
as_eval(np)
register NODEP np;
{
NODEP rp = np->n_right;
register int op, i, r;
rp = np->n_right;
op = np->g_token;
op -= ASSIGN 0;
switch (op) {
/* these get unfolded now */
case '*':
return fixamul(np, bops[0].opflags);
case '/':
return fixadiv(np, bops[1].opflags);
case '%':
return fixamod(np, bops[2].opflags);
case '&': i = 3; goto doop;
case '|': i = 4; goto doop;
case '^': i = 5; goto doop;
case '+': i = 6; goto doop;
case '-': i = 7; goto doop;
case DOUBLE '<':i = 8; goto doop;
case DOUBLE '>':i = 9;
doop:
strcpy(np->n_name, np->g_ty == ET_U ?
bops[i].u_op : bops[i].s_op);
r = fix_asn(np, bops[i].opflags);
cc_hack(np);
return r;
default:
printf("Weird as_eval %s ", np->n_name);
return FAIL;
}
}
rinherit(np)
register NODEP np;
{
register NODEP rp = np->n_right;
np->g_token = rp->g_token;
np->g_offs = rp->g_offs;
np->g_rno = rp->g_rno;
np->g_flags |= RCHILDNM | (rp->g_flags & IMMEDID);
}
argmod(np)
register NODEP np;
{
int size = 0;
if (np->g_token == ',') {
np->g_type = EV_RL;
size += argmod(np->n_right);
size += argmod(np->n_left);
return size;
}
size += onearg(np);
return size;
}
onearg(np)
register NODEP np;
{
int rv;
/* hack small ICON */
if (np->g_sz == 1 && np->g_token == ICON)
np->g_sz = 2;
/* hack push of 0 */
if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) {
addcode(np, "\tclr.S\t-(sp)\n");
return (int)np->g_sz;
}
/* hack push of #OREG */
if (np->g_token == OREG && isimmed(np)) {
np->g_flags &= ~IMMEDID;
addcode(np, "\tpea\tA\n");
return 4;
}
if (np->g_ty == ET_A) {
rv = np->g_bsize;
strpush(np);
freetmps(np);
free1(NULL,np);
return rv;
}
switch (np->g_sz) {
case 1:
addcode(np,
"\tmove.b\tA,d0\n\text.w\td0\n\tmove.w\td0,-(sp)\n");
return 2;
case 2:
addcode(np,
"\tmove.w\tA,-(sp)\n");
return 2;
default:
addcode(np,
"\tmove.l\tA,-(sp)\n");
return 4;
}
}
#define MAXD DRV_START
#define MAXA (ARV_START-AREG)
#define NEEDALL (MAXA*AREG + MAXD)
order(np)
register NODEP np;
{
int l, r;
switch (np->g_type) {
case E_BIN:
order(np->n_right);
r = np->n_right->g_needs;
case E_UNARY:
order(np->n_left);
l = np->n_left->g_needs;
break;
default: /* leaf */
np->g_type = EV_NONE;
np->g_needs = 0;
return;
}
if (np->g_type == E_UNARY) {
switch (np->g_token) {
case STAR:
np->g_needs = merge(l,AREG);
break;
case '(':
np->g_needs = NEEDALL;
break;
case POSTINC:
case POSTDEC:
case '!':
np->g_needs = merge(l,1);
break;
case '.':
if (np->g_fldw) {
np->g_needs = merge(l,1);
break;
}
/* else fall through */
default:
np->g_needs = l;
}
np->g_type = EV_LEFT;
return;
}
/* at this point, have binary node */
switch (np->g_token) {
case DOUBLE '&':
case DOUBLE '|':
case '?':
case ':':
/* always left-right, no extra regs */
np->g_type = EV_LRSEP;
np->g_needs = merge(1, merge(l,r));
return;
case ',':
np->g_needs = merge(l, r);
np->g_type = EV_LRSEP;
return;
case '(':
np->g_needs = NEEDALL;
break;
case '^':
case DOUBLE '<':
case DOUBLE '>':
case ASSIGN '/':
case ASSIGN DOUBLE '<':
case ASSIGN DOUBLE '>':
np->g_needs = merge(bin(l,r), 2);
break;
default:
np->g_needs = merge(bin(l,r), 1);
}
if (isassign(np->g_token) || np->g_token == '=')
np->g_type = EV_RL; /* NO PUSHER's on L */
else
np->g_type = worst_1st(l, r);
flag_saves(np, l, r);
}
flag_saves(np, l, r)
NODEP np;
{
NODEP *cpp;
register int other;
if (np->g_type == EV_LR) {
cpp = &np->n_left;
other = r;
} else {
cpp = &np->n_right;
other = l;
}
if ((other & 7) >= MAXD || (other/AREG) >= MAXA)
addtmp(np, cpp);
}
addtmp(np, cpp)
NODEP np, *cpp;
{
NODEP cp, tp;
NODEP copyone();
cp = *cpp;
tp = copyone(cp);
tp->n_left = cp;
*cpp = tp;
tp->g_token = PUSHER;
strcpy(tp->n_name, "pusher");
tp->g_type = EV_LEFT;
}
worst_1st(l,r)
{
int ld, rd;
ld = l & 7;
rd = r & 7;
if (rd > ld)
return EV_RL;
if (r > l)
return EV_RL;
return EV_LR;
}
bin(l,r)
{
int la, ra, na;
int ld, rd, nd;
la = l/AREG;
ra = r/AREG;
ld = l & 7;
rd = r & 7;
na = la > ra ? la : ra;
if (ld == rd)
nd = ld == MAXD ? MAXD : ld+1;
else
nd = ld > rd ? ld : rd;
return na*AREG + nd;
}
merge(need, have)
{
int na, nd, ha, hd, xa, xd;
na = need/AREG;
ha = have/AREG;
nd = need & 7;
hd = have & 7;
xa = na > ha ? na : ha;
xd = nd > hd ? nd : hd;
return xa*AREG + xd;
}
holdlbls(np)
NODEP np;
{
np->g_bsize = new_lbl();
new_lbl();
}
rinhlbls(np)
NODEP np;
{
np->g_bsize = np->n_right->g_bsize;
}
/* limited version of same address check
assume one of these is a temp register */
same_a(p1, p2)
NODEP p1, p2;
{
if (p1->g_token != p2->g_token)
return 0;
if (p1->g_rno != p2->g_rno)
return 0;
return 1;
}
optadd(np, flags, sign)
register NODEP np;
{
NODEP lp = np->n_left, rp = np->n_right;
if (rp->g_token != ICON)
return 0;
if (isimmed(lp) && isimmed(rp)) {
switch (lp->g_token) {
case OREG:
case ONAME:
inherit(np);
if (sign == -1)
rp->g_offs = -rp->g_offs;
np->g_offs += rp->g_offs;
if ((flags & IMMA_OK) == 0)
imm_oreg(np);
return 1;
default:
return 0;
}
}
return 0;
}
iscc(np)
NODEP np;
{
return (np->g_token >= BR_TOK) || (np->g_flags & SIDE_CC);
}
cc_hack(np)
NODEP np;
{
if (isareg(np))
return;
np->g_flags |= SIDE_CC;
}
cctok(np)
NODEP np;
{
if (np->g_token >= BR_TOK)
return np->g_token - BR_TOK;
if (np->g_flags & SIDE_CC)
return B_NE;
printf("cctok error ");
return 0;
}
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.